/*
Copyright 2010,2011 Matt Van Der Westhuizen

This file is part of CGLL.

CGLL is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

CGLL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with CGLL.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.chaoticengine.cgll.entity.component.render;

import org.chaoticengine.cgll.entity.component.RenderComponent;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.StateBasedGame;
import org.simpleframework.xml.Element;

/**
 * Component for rendering game entities by using a image representation. The
 * bounding rectangle for the entity is set as the size of the image.
 *
 * @author Matt v.d. Westhuizen
 */
public class AnimationRenderComponent extends RenderComponent {
    protected SpriteSheet sprite = null;
    protected boolean rotate = true;
    protected int frame = 0;
    protected int cellW = 16;
    protected int cellH = 16;
    protected int frameDelay = 250;
    protected int timeWaited = 0;
    protected long lastTimeStamp = 0;

    public AnimationRenderComponent() {
        super();
    }

    @Element(name="sprite", required=true)
    public String getSprite() {
        if (sprite != null) {
            return(sprite.getResourceReference());
        } else {
            return("");
        }
    }

    @Element(name="sprite", required=true)
    public void setSprite(String filename) {
        try {
            this.sprite = new SpriteSheet(new Image(filename), cellW, cellH);
        } catch (SlickException sEx) {
            sEx.printStackTrace();
            System.out.println("Error: Failed to load sprite '" + filename + "'.");
        }
    }

    public boolean isRotate() {
        return rotate;
    }

    public void setRotate(boolean rotate) {
        this.rotate = rotate;
    }

    @Override
    public void onSetOwner() {
        Vector2f pos = owner.getPosition();
        owner.setBounds(new Rectangle(pos.getX() - cellW / 2.0f,
                pos.getY() - cellH / 2.0f,
                cellW,
                cellH));
        owner.setPosition(new Vector2f(owner.getBounds().getCenter()));
        owner.setTranslation(new Vector2f(-cellW / 2.0f, -cellH / 2.0f));
    }

    @Override
    public void render(GameContainer gc, StateBasedGame sb, Graphics gr) {
        // Update
        if (lastTimeStamp == 0) {
            lastTimeStamp = gc.getTime();
        } else {
            long newTime = gc.getTime();
            timeWaited += newTime - lastTimeStamp;
            lastTimeStamp = newTime;

            if (timeWaited >= frameDelay) {
                frame++;
            }

            if (frame >= sprite.getHorizontalCount()) {
                frame = 0;
            }
        }

        // Translation & rotation
        gr.translate(owner.getPosition().x, owner.getPosition().y);
        if (rotate) {
            gr.rotate(0.0f, 0.0f, owner.getRotation());
        }
        gr.translate(owner.getTranslation().x, owner.getTranslation().y);

        // Rendering
        Image img = sprite.getSprite(frame, 0);
        img.setAlpha(owner.getAlpha());
        gr.drawImage(img, 0.0f, 0.0f);

        // Undo translation & rotation
        gr.translate(-owner.getTranslation().x, -owner.getTranslation().y);
        if (rotate) {
            gr.rotate(0.0f, 0.0f, -owner.getRotation());
        }
        gr.translate(-owner.getPosition().x, -owner.getPosition().y);
    }
}
